package com.liuguoqing.framework.context.support;

import com.liuguoqing.framework.beans.BeanDefinition;
import com.liuguoqing.framework.beans.PropertyValue;
import com.liuguoqing.framework.beans.factory.support.BeanDefinitionRegistry;
import com.liuguoqing.framework.beans.factory.xml.XmlBeanDefinitionReader;
import com.liuguoqing.framework.utils.StringUtils;

import java.lang.reflect.Method;

/**
 * @Author : liugq
 * @Date : 2022/7/19 23:47
 * @See : 参考类
 * @Since： JDK1.8
 * @Version : 1.0
 */
public class ClassPathXmlApplicationContext  extends AbstractApplicationContext {

    public ClassPathXmlApplicationContext(String configLocation) {
        this.configLocation = configLocation;
        //构建XmlBeanDefinitionReader对象
        beanDefinitionReader = new XmlBeanDefinitionReader();
        try {
            this.refresh();
        } catch (Exception e) {
        }
    }



    /**
     * 根据bean对象的名称获取bean对象
     *
     * @param name
     */
    @Override
    public Object getBean(String name) throws Exception {
        //判断集合中是否存在当前Bean
        Object obj = singletonObjects.get(name);
        if ( null != obj)
            return obj;

        //不存在，则创建Bean
            //1:从注册表中获取当前bean的相关信息
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        BeanDefinition beanDefinition = registry.getBeanDefinition(name);
            //2:判断是否有信息
        if ( null == beanDefinition )
            return null;

            //3:创建bean
        String className = beanDefinition.getClassName();
        Class<?> clazz = Class.forName(className);
        Object o = clazz.newInstance();
            //4:依赖注入
        PropertyValue[] propertyValues = beanDefinition.getPropertyValues().getPropertyValues();
        for (PropertyValue propertyValue : propertyValues) {
            String propertyName = propertyValue.getName();
            String value = propertyValue.getValue();
            String ref = propertyValue.getRef();

            //4.1： 有引用
            if(ref != null && !"".equals(ref)) {
                Object bean = getBean(ref);
                String methodName = StringUtils.setterMethodByFieldName(propertyName);
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    if(method.getName().equals(methodName)) {
                        method.invoke(o,bean);
                        break;
                    }
                }
            }

            //4.2：赋值
            if(value != null && !"".equals(value)) {
                String methodName = StringUtils.setterMethodByFieldName(propertyName);
                Method method = clazz.getMethod(methodName, String.class);
                method.invoke(o,value);
            }
        }

        singletonObjects.put(name,o);
        return o;
    }

    /**
     * 根据bean对象的名称获取bean对象，并进行类型转换
     *
     * @param name
     * @param clazz
     */
    @Override
    public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {
        Object bean = getBean(name);
        if(bean != null) {
            return clazz.cast(bean);
        }
        return null;
    }
}
